---继承
---@generic T
---@param super? T
---@return T
local function extend(super)
    super = super or {}
    return setmetatable({ super = super }, {
        __index = super,
        __call = function(owner, ...)
            local ins = extend(owner)
            if ins.ctor then ins:ctor(...) end
            return ins
        end
    })
end

---@class tablelib
table = extend(table);
table.extend = extend;

---数组映射
---@param tab table 阿萨德
---@param func fun(v:any,n:number) 次数
function table.map(tab, func)
    for i = 1, #tab, 1 do
        local ret = func(tab[i], i)
        tab[i] = ret
    end
    return tab
end

---数组反向
---@param arr table 数组
function table.reverse(arr)
    local i = 0
    local j = #arr - 1
    while i < j do
        local temp = arr[j + 1]
        arr[j + 1] = arr[i + 1]
        arr[i + 1] = temp
        i = i + 1
        j = j - 1
    end
    return arr
end

--表序列化
table.tostring = function(t)
    if t then
        local mark = {}
        local assign = {}
        local function sertableUtil(tbl, parent)
            mark[tbl] = parent
            local tmp = {}
            for k, v in pairs(tbl) do
                local key
                if type(k) == "number" then
                    key = "[" .. k .. "]"
                elseif tonumber(k) ~= nil then
                    key = "[" .. string.format("%q", k) .. "]"
                else
                    key = k
                end
                if type(v) == "string" then
                    table.insert(tmp, key .. "=" .. string.format("%q", v))
                elseif type(v) == "number" or type(v) == "boolean" then
                    table.insert(tmp, key .. "=" .. tostring(v))
                elseif type(v) == "table" then
                    local dkey = type(k) == "number" and "[" .. k .. "]" or "[" .. string.format("%q", k) .. "]"
                    local dotkey = parent .. dkey
                    if mark[v] then
                        table.insert(assign, dotkey .. "=" .. mark[v])
                    else
                        table.insert(tmp, key .. "=" .. sertableUtil(v, dotkey))
                    end
                end
            end
            return "{" .. table.concat(tmp, ",") .. "}"
        end

        return sertableUtil(t, "ret") .. table.concat(assign, ";")
    end
end
--载入序列化表
table.loadstring = function(t)
    if t and type(t) == "string" then --兼容
        local f = loadstring(t:byte() == 100 and t or ("do local ret=" .. t .. " return ret end"))
        if f then
            setfenv(f, {})
            return f()
        end
    end
    --return {}
end
--表复制
table.copy = function(old_tab)
    local new_tab = {}
    if old_tab and type(old_tab) == "table" then
        for i, v in pairs(old_tab) do
            local vtyp = type(v)
            if (vtyp == "table") then
                new_tab[i] = table.copy(v)
            elseif (vtyp == "string" or vtyp == "number" or vtyp == "boolean") then
                new_tab[i] = v
            else
                error("不支持复制")
            end
        end
    end
    return new_tab
end
---表打印
table.print = function(tab)
    if type(tab) == "cdata" then
        return
    end
    if tab then
        local print = print
        local tconcat = table.concat
        local tinsert = table.insert
        local srep = string.rep
        local type = type
        local pairs = pairs
        local tostring = tostring
        local next = next
        local cache = { [tab] = "." }
        local function _dump(t, space, name)
            local temp = {}
            if next(t) then
                tinsert(temp, "{")
                for k, v in pairs(t) do
                    local key = tostring(k)
                    if cache[v] then
                        tinsert(temp, "\t" .. key .. "={" .. cache[v] .. "}")
                    elseif type(v) == "table" then
                        local new_key = name .. "." .. key
                        cache[v] = new_key
                        tinsert(temp, "\t" .. key .. "=" .. _dump(v, space .. srep("\t", #key), new_key))
                    else
                        tinsert(temp, "\t" .. key .. "=" .. tostring(v))
                    end
                end
                tinsert(temp, "}")
            else
                tinsert(temp, "{}")
            end

            return tconcat(temp, "\n" .. space)
        end

        print("-------------------------------------")
        print(tab)
        print(_dump(tab, "", ""))
        print("-------------------------------------")
    end
end
function table.removeAll(t)
    for k in pairs(t) do
        t[k] = nil
    end
end

function table.indexOf(table, value)
    for k, v in ipairs(table) do
        if v == value then
            return k
        end
    end
    return -1
end

---从数组/字典中提取部分成员出来转换成字典 成员留空提取全部 也可以用作数组转成字典
function table.extract(tab, ...)
    local newTab = {}
    local args = { ... }
    if table.isDict(tab) then
        if #args > 0 then
            for _, ele in ipairs({ ... }) do
                if tab[ele] then
                    newTab[ele] = tab[ele]
                end
            end
        end
    else
    end
    return newTab
end
function table.shift(tab)
    return table.remove(tab, 0);
end
function table.pop(tab)
    return table.remove(tab, #tab);
end

---是否是哈希数组
---@param tab table 表
---@return boolean
function table.isDict(tab)
    if type(tab) == "table" then
        if next(tab) then
            return true
        end
    end
    if type(tab) == "cdata" then
        return true
    end
    return false
end

function table.isArray(tab)
    return not table.isDict(tab)
end

---@class metatab
---@field indexOf fun(value):number 查找表 返回索引
---@field removeAll fun():metatab 清空表
---@field isDict fun():boolean 是否是哈希数组
---@field isArray fun():boolean 是否是有序数组
---@field insert fun(value):metatab 插入数组



---创建一个具有链式操作的表
---@return metatab
function table.create(tab)
    tab = tab or {}
    return setmetatable(tab, {
        __index = function(owner, k)
            if table[k] then
                return function(...)
                    local ret = { table[k](owner, ...) }
                    if #ret >= 1 then
                        return unpack(ret)
                    else
                        return owner
                    end
                end
            else
                return owner
            end
        end
    })
end

---new一个新的表
---@generic T
---@param class T
---@return T
function table.new(class, ...)
    local ins = table.extend(class)
    if ins.ctor then ins:ctor(...) end
    return ins
end
